{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "7717416e",
   "metadata": {},
   "source": [
    "***本项目是用来演示使用中文菜谱数据调优ChatGLM2-6B***"
   ]
  },
  {
   "cell_type": "raw",
   "id": "9fda328f-4df9-4e17-97f4-a9f8d359bd8c",
   "metadata": {},
   "source": [
    "红烧鸡翅\n",
    "萝卜丝鲫鱼汤\n",
    "沙茶牛肉\n",
    "五彩鳝丝\n",
    "香菇鲜肉盏\n",
    "碧绿虾仁\n",
    "剁椒蒸鱼头\n",
    "黑椒牛柳\n",
    "蜜橘鸡丁\n",
    "土家一罐香"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "3ff21857-79bc-4b12-aaed-4f7d235f6132",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 测试的菜名\n",
    "test_query = \"蕉牛奶西米捞\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "33afe751-a1d9-472f-b564-769613e5d986",
   "metadata": {},
   "source": [
    "## 1.预训练模型能力"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "322bc85d-fee7-4268-ab5e-400b9c953a3a",
   "metadata": {},
   "outputs": [],
   "source": [
    "from transformers import  AutoModel,AutoTokenizer, BitsAndBytesConfig\n",
    "import torch\n",
    "torch.cuda.empty_cache()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "0d6b625a-ab66-4e55-9331-0f09b161e238",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/json": {
       "ascii": false,
       "bar_format": null,
       "colour": null,
       "elapsed": 0.02134394645690918,
       "initial": 0,
       "n": 0,
       "ncols": null,
       "nrows": null,
       "postfix": null,
       "prefix": "Loading checkpoint shards",
       "rate": null,
       "total": 7,
       "unit": "it",
       "unit_divisor": 1000,
       "unit_scale": false
      },
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "20a3adf0375c4a4386116755e6aa8b45",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Loading checkpoint shards:   0%|          | 0/7 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "model_name = \"./models/chatglm2-6b\" #  #或者远程 “THUDM/chatglm2-6b”\n",
    "# .cache/huggingface/hub/models--THUDM--chatglm2-6b/snapshots/4e38bef4c028beafc8fb1837462f74c02e68fcc2/\n",
    "\n",
    "bnb_config = BitsAndBytesConfig(\n",
    "    load_in_4bit=True,\n",
    "    bnb_4bit_compute_dtype=torch.float16,\n",
    "    bnb_4bit_use_double_quant=True, #QLoRA 设计的 Double Quantization\n",
    "    bnb_4bit_quant_type='nf4', # QLoRA 设计的 Normal Float 4 量化数据类型\n",
    "    llm_int8_threshold=6.0,\n",
    "    llm_int8_has_fp16_weight=False,\n",
    ")\n",
    "\n",
    "tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)\n",
    "model_base = AutoModel.from_pretrained(model_name,\n",
    "                                  quantization_config=bnb_config,\n",
    "                                  trust_remote_code=True) #.half().cuda()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "ee3506b8-67bf-4f60-b22e-eaa61122d073",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用 Markdown 格式打印模型输出\n",
    "from IPython.display import display, Markdown, clear_output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "cde1d6f9-6ec8-4fa9-9047-c5d70dca4c3c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 测试base的能力\n",
    "def display_answer_base(query, history=[]):\n",
    "    for response, history in model_base.stream_chat(\n",
    "            tokenizer, query, history=history):\n",
    "        clear_output(wait=True)\n",
    "        display(Markdown(response))\n",
    "    return history"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "a6142fd7-d416-4967-9ef6-608f618fab5e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "蕉牛奶西米捞是一种传统的华南小吃,主要流行于广东、福建、海南等地区。主要由西米、香蕉、牛奶和糖等食材烹制而成。\n",
       "\n",
       "烹制方法是先将香蕉切成小块,加入锅中慢慢煮至软烂。然后加入西米和牛奶,搅拌均匀。最后加入适量的糖,继续煮至糖完全溶解即可。\n",
       "\n",
       "蕉牛奶西米捞口感香甜可口,营养丰富,是很多人喜爱的美食之一。"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "h = display_answer_base(test_query,[])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "f85ef7db-e97b-492f-8d4a-36fa3835b5d0",
   "metadata": {},
   "outputs": [],
   "source": [
    "## 1 epoch能力"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "37d94587",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "torch.cuda.empty_cache()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "214a8284",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/json": {
       "ascii": false,
       "bar_format": null,
       "colour": null,
       "elapsed": 0.0162966251373291,
       "initial": 0,
       "n": 0,
       "ncols": null,
       "nrows": null,
       "postfix": null,
       "prefix": "Loading checkpoint shards",
       "rate": null,
       "total": 7,
       "unit": "it",
       "unit_divisor": 1000,
       "unit_scale": false
      },
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "4b535e0c5fcb4d4190cfd531aeb63e84",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Loading checkpoint shards:   0%|          | 0/7 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from transformers import  AutoModel,AutoTokenizer, BitsAndBytesConfig\n",
    "from peft import PeftModel\n",
    "\n",
    "model_name = \"./models/chatglm2-6b\" #\"../chatglm2-6b\" #或者远程 “THUDM/chatglm2-6b”\n",
    "tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)\n",
    "model_a = AutoModel.from_pretrained(model_name,\n",
    "                                  load_in_8bit=False,\n",
    "                                  trust_remote_code=True,\n",
    "                                  device_map='auto')\n",
    "ckpt_path_a = 'meishi_chatglm2_qlora_1epoch'\n",
    "model_a = PeftModel.from_pretrained(model_a, ckpt_path_a)\n",
    "model_a = model_a.merge_and_unload() # 合并QLoRA的权重"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "576e5aa3-97b2-4503-aae8-1493f8a5cd46",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1 epoch能力\n",
    "def display_answer_1epoch(query, history=[]):\n",
    "    for response, history in model_a.stream_chat(\n",
    "            tokenizer, query, history=history):\n",
    "        clear_output(wait=True)\n",
    "        display(Markdown(response))\n",
    "    return history"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "416809e0-d348-45b4-b9f8-102cf966abdd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "食材明细: \n",
       "香蕉 : 1根 \n",
       "西米 : 适量 \n",
       "牛奶 : 适量 \n",
       "\n",
       "制作步骤: \n",
       "第1步：香蕉去皮切小块，放入搅拌机打成泥。第2步：将香蕉泥倒入小锅中，加入牛奶，搅拌均匀。第3步：倒入小锅中，用中小火煮至沸腾。第4步：将煮好的香蕉牛奶倒入容器中，放凉后加入西米。第5步：用保鲜膜盖住容器，放入冰箱冷藏2小时。第6步：第二天早晨，取出香蕉牛奶，放入蒸锅中蒸15分钟即可。\n",
       "制作方法: \n",
       "煮十分钟"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "h = display_answer_1epoch(test_query,[])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "1f414ca7-5c82-44d6-af47-e97626c13d5d",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "torch.cuda.empty_cache()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "4c70d1f5-371e-4ae6-987c-dcb803e61650",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/json": {
       "ascii": false,
       "bar_format": null,
       "colour": null,
       "elapsed": 0.02028632164001465,
       "initial": 0,
       "n": 0,
       "ncols": null,
       "nrows": null,
       "postfix": null,
       "prefix": "Loading checkpoint shards",
       "rate": null,
       "total": 7,
       "unit": "it",
       "unit_divisor": 1000,
       "unit_scale": false
      },
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "74759739a653472eb0490549ca3e371b",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Loading checkpoint shards:   0%|          | 0/7 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from transformers import  AutoModel,AutoTokenizer, BitsAndBytesConfig\n",
    "from peft import PeftModel\n",
    "\n",
    "model_name = \"./models/chatglm2-6b\" #\"../chatglm2-6b\" #或者远程 “THUDM/chatglm2-6b”\n",
    "tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)\n",
    "model_b = AutoModel.from_pretrained(model_name,\n",
    "                                  load_in_8bit=False,\n",
    "                                  trust_remote_code=True,\n",
    "                                  device_map='auto')\n",
    "ckpt_path_b = 'meishi_chatglm2_qlora_3epoch'\n",
    "model_b = PeftModel.from_pretrained(model_b, ckpt_path_b)\n",
    "model_b = model_b.merge_and_unload() # 合并QLoRA的权重"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f3405557-33ba-4c59-aafb-d0313c30399f",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "f004c39d-e41a-49dd-876c-853b6e31d1b9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 测试3 epoch的能力\n",
    "# 1 epoch能力\n",
    "def display_answer_3epoch(query, history=[]):\n",
    "    for response, history in model_a.stream_chat(\n",
    "            tokenizer, query, history=history):\n",
    "        clear_output(wait=True)\n",
    "        display(Markdown(response))\n",
    "    return history"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "bb3d9b39-9b1c-4e38-a290-3c798b439d9c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "食材明细: \n",
       "香蕉 : 适量 \n",
       "西米 : 适量 \n",
       "牛奶 : 适量 \n",
       "\n",
       "制作步骤: \n",
       "第1步：香蕉剥皮切小块第2步：西米洗净浸泡20分钟第3步：香蕉切小块第4步：把香蕉和牛奶一起放入锅中第5步：加适量水煮第6步：煮至香蕉和牛奶一起变稠第7步：放西米一起煮至西米粘稠第8步：放冰箱冷藏一下，就可以享用了\n",
       "制作方法: \n",
       "煮十分钟"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "h = display_answer_3epoch(test_query,[])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "d6473a2d-7816-4371-9135-bbd6e11599a7",
   "metadata": {},
   "outputs": [],
   "source": [
    "integrate = \"牛肉片 : 300克 \\n青椒片 : 75克 \\n洋葱片 : 50克 \\n沙茶酱 : 75克 \\n白糖 : 20克 \\n白酱油 : 20克 \\n淀粉 : 30克 \\n蒜末 : 10克 \\n花生酱 : 35克 \\n味精 : 3克 \\n熟猪油 : 适量 \\n\"\n",
    "step = \"第1步：牛肉片用白酱油抓匀，再加淀粉拌匀。第2步：将牛肉片加入沙茶酱、花生酱、白糖、蒜末、味精、再放入青椒片、洋葱片淋上熟猪油拌匀，用高档火打6分钟即可。\"\n",
    "method = \"炒廿分钟\"\n",
    "prompt = \"\" + '\\n' + '食材明细: \\n' + integrate + '\\n' + \"制作步骤: \\n\" + step + '\\n' + \"制作方法: \\n\" + method + '\\n'\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "c47eff99-4d67-45f6-beab-2fa9becbabfe",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "以上步骤是菜品【牛肉沙茶】的制作方法"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "h = display_answer_1epoch(prompt,[])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c540ae6a-15c0-4b98-bb24-29850cddcfec",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
